package com.liz.lizrpccore.core.providers.netty;

import com.alibaba.fastjson.JSON;
import com.liz.lizrpccore.beans.proxys.netty.msgs.InvokerMessage;
import com.liz.lizrpccore.core.LizRpcConfig;
import com.liz.lizrpccore.entity.LizRpcArg;
import com.liz.lizrpccore.utils.SpringContextUtils;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @author liangGongWei
 * @description  通过反射调用 spring上下文中的bean 对应的方法
 * @create 2021-09-22 15:10
 **/

public class MyReflectInvokingHandler extends ChannelInboundHandlerAdapter {

    private static final Logger log = LoggerFactory.getLogger(MyReflectInvokingHandler.class);

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object obj) throws Exception {
        Object result = new Object();
        InvokerMessage message = (InvokerMessage) obj;

        String className = message.getClassName();
        LizRpcConfig lizRpcConfig = SpringContextUtils.getApplicationContext().getBean(LizRpcConfig.class);
        if (lizRpcConfig.classNameList.contains(className)){
            return;
        }

        List<Object> args = this.getArgs(message.getLizRpcArgs());
        Object[] params = args.toArray();
        Class<?>[] paramsType = this.getParamsType(params);

        Object clazz = SpringContextUtils.getApplicationContext().getBean(message.getClassName());
        Method method = clazz.getClass().getMethod(message.getMethodName(), paramsType);
        result = method.invoke(clazz, params);
        log.info("message:{},result:{}",message,result);
        ctx.writeAndFlush(result);
        ctx.close();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }

    private List<Object> getArgs(List<LizRpcArg> argsList) {
        try {
            List<Object> res = new ArrayList<>();
            for (LizRpcArg arg : argsList) {
                Class<?> clazz = Class.forName(arg.getClassName());
                Object o = JSON.parseObject(arg.getObjStr(), clazz);
                res.add(o);
            }
            return res;
        } catch (Exception e) {
            throw new RuntimeException("参数转化异常：" + argsList);
        }
    }

    private Class<? extends Object>[] getParamsType(Object[] params){
        Class<? extends Object>[] paramClass = null;
        if (params != null) {
            int paramsLength = params.length;
            paramClass = new Class[paramsLength];
            for (int i = 0; i < paramsLength; i++) {
                paramClass[i] = params[i].getClass();
            }
        }
        return paramClass;
    }


}
